package api

import (
	"errors"
	"jgt-oper/src/bll"
	"jgt-oper/src/context"
	"jgt-oper/src/schema"
	"jgt-oper/src/util"
	"time"
)

// PublicResourceController 移动端公共资源
type PublicResourceController struct {
	UserBll             *bll.User               `inject:""`
	EnterpriseBll       *bll.Enterprise         `inject:""`
	ResourceBll         *bll.ResourceManagement `inject:""`
	ParkBll             *bll.Park               `inject:""`
	ResourceClassBll    *bll.RCBll              `inject:""`
	ResourceReservedBll *bll.ResourceReserved   `inject:""`
}

// GetDefaultApplicant 默认可用资源信息
func (a *PublicResourceController) GetDefaultApplicant(ctx *context.Context) error {
	ctx.WriteOperateLog("PublicResourceController.GetDefaultApplicant", "移动端-公共资源-获取默认用户信息")
	//	当前用户id
	userID := ctx.GetUserID()

	// 1.申请人基本信息的
	applicantMap := make(map[string]interface{})
	// 查询用户信息
	userItem, err := a.UserBll.Get(userID)
	if err != nil {
		return ctx.ResErrInternalServer(err)
	}
	if userItem == nil {
		return ctx.ResErrInternalServer(errors.New("空指针错误，或者当前用户的record_id失效"))
	}
	// 认证信息
	authUserItem, err := a.UserBll.GetAuthUser(userID)
	if err != nil {
		return ctx.ResErrInternalServer(err)
	}
	if authUserItem == nil {
		return ctx.ResErrInternalServer(errors.New("空指针错误，或者当前用户的record_id失效"))
	}
	// 企业信息
	if userItem.EnterpriseID != "" {
		enterpriseItem, err := a.EnterpriseBll.Get(userItem.EnterpriseID)
		if err != nil {
			return ctx.ResErrInternalServer(err)
		}
		if enterpriseItem == nil {
			return ctx.ResErrInternalServer(errors.New("空指针错误，或者当前用户的enterprise_id失效"))
		}
		applicantMap["enterprise_name"] = enterpriseItem.Name
	}
	applicantMap["contact_tel"] = authUserItem.Tel
	applicantMap["contact_name"] = userItem.RealName

	//	2.组装返回数据
	result := make(map[string]interface{})
	result["applicant"] = applicantMap

	return ctx.ResSuccess(result)
}

// GetDefaultResources 默认可用资源信息
func (a *PublicResourceController) GetDefaultResources(ctx *context.Context) error {
	ctx.WriteOperateLog("PublicResourceController.GetDefaultResources", "移动端-公共资源-获取默认资源信息")

	//	1.公共资源信息
	resItems, err := a.ResourceBll.QueryAvailableRes()
	if err != nil {
		return ctx.ResErrInternalServer(err)
	}
	resMapArray := make([]map[string]interface{}, 0)
	for _, item := range resItems {
		tempMap := make(map[string]interface{})
		//	资源record_id
		tempMap["record_id"] = item.RecordID
		//	资源名称
		tempMap["resource_name"] = item.ResourceName
		//	资源所属区域名称
		if item.AddressZone == "" {
			return ctx.ResErrInternalServer(errors.New("资源所属区域的record_id为空"))
		}
		parkItem, err := a.ParkBll.Get(item.AddressZone)
		if err != nil {
			return ctx.ResErrInternalServer(err)
		}
		if parkItem == nil {
			return ctx.ResErrInternalServer(errors.New("空指针错误，或者资源所在区域的record_id失效"))
		}
		tempMap["address_zone"] = parkItem.Name
		//	资源所属分类名称
		if item.ClassificationID == "" {
			return ctx.ResErrInternalServer(errors.New("资源所属分类的record_id为空"))
		}
		classItem, err := a.ResourceClassBll.Get(item.ClassificationID)
		if err != nil {
			return ctx.ResErrInternalServer(err)
		}
		tempMap["class_name"] = classItem.ClassificationName
		resMapArray = append(resMapArray, tempMap)
	}
	//	2.组装返回数据
	result := make(map[string]interface{})
	result["resources"] = resMapArray

	return ctx.ResSuccess(result)
}

// GetResource 查询资源基本信息
func (a *PublicResourceController) GetResource(ctx *context.Context) error {
	ctx.WriteOperateLog("PublicResourceController.GetResource", "移动端-公共资源-查询资源信息和当前预定情况")
	//	资源的record_id
	resID := ctx.Query("id")
	if resID == "" {
		return ctx.ResErrBadRequest(errors.New("id参数错误"))
	}
	//	查询详情
	resItem, err := a.ResourceBll.Get(resID)
	if err != nil {
		return ctx.ResErrInternalServer(err)
	}
	if resItem == nil {
		return ctx.ResErrInternalServer(errors.New("空指针错误，或者当前资源的record_id失效"))
	}
	resultMap := make(map[string]interface{})
	//	资源管理员
	resultMap["manager"] = resItem.Manager
	//	管理员电话
	resultMap["telephone"] = resItem.Telephone
	//	资源所属区域名称
	if resItem.AddressZone == "" {
		return ctx.ResErrInternalServer(errors.New("资源所属区域的record_id为空"))
	}
	fullName, err := a.ParkBll.QueryFullName(resItem.AddressZone)
	if err != nil {
		return ctx.ResErrInternalServer(err)
	}
	resultMap["address_zone"] = fullName
	//	地址
	resultMap["address"] = resItem.Address
	//	可用状态
	resultMap["available_status"] = resItem.AvailableStatus
	//	价格
	resultMap["price"] = resItem.Price

	// 资源描述
	resultMap["comment"] = resItem.Comment
	//	资源图片
	resultMap["pictures"] = resItem.Pictures
	return ctx.ResSuccess(resultMap)
}

// GetReserveInfo 查询指定资源的预定情况
func (a *PublicResourceController) GetReserveInfo(ctx *context.Context) error {
	ctx.WriteOperateLog("PublicResourceController.GetReserveInfo", "移动端-公共资源-查询资源信息和当前预定情况")
	//	资源的record_id
	resourceID := ctx.Query("id")
	date := ctx.Query("date")
	if resourceID == "" {
		return ctx.ResErrBadRequest(errors.New("id参数错误"))
	}
	if date == "" {
		return ctx.ResErrBadRequest(errors.New("date参数错误"))
	}
	//	查询资源详情
	resourceItem, err := a.ResourceBll.Get(resourceID)
	if err != nil {
		return ctx.ResErrInternalServer(err)
	}
	if resourceItem == nil {
		return ctx.ResErrInternalServer(errors.New("空指针错误，或者当前资源的record_id失效"))
	}
	resultMap := make(map[string]interface{})

	//	查询指定资源、指定日期的预定情况
	reservedItems, err := a.ResourceReservedBll.QueryItems(resourceID, date)
	if err != nil {
		return ctx.ResErrInternalServer(errors.New("查询资源预定信息时发生错误"))
	}

	//	资源设置状态
	tempMap := make(map[int]int)
	for _, value := range resourceItem.AvailableTime {
		tempMap[value] = 1
	}

	//	遍历已经预定的信息条目，然后标记可预定时间、不可用时间、已预定时间
	for _, reservedItem := range reservedItems {
		//	今天的预定情况
		reservedHours := reservedItem.HoursReserved[date]
		for _, hour := range reservedHours {
			reservedID := reservedItem.RecordID
			if hour > 23 || hour < 0 {
				return ctx.ResErrInternalServer(errors.New("数据库存储的hours_reserved存在超范围数据:record_id ->" + reservedID))
			}
			h, ok := tempMap[hour]
			if ok && h == 1 {
				//	当前预约时间可选
				//	设置标记
				tempMap[hour] = 2
			} else if ok && h == 2 {
				return ctx.ResErrInternalServer(errors.New("数据库表错误:存在相同预约时间数据:资源预定数据表:record_id:" + reservedID))
			} else if !ok {
				return ctx.ResErrInternalServer(errors.New("数据库表错误:预约时间不可选:资源预定数据表:record_id:" + reservedID))
			}
		}
	}
	//	返回数组
	availableArray := make([]int, 24)
	//	从map中取出放入数组合适位置
	for key, value := range tempMap {
		availableArray[key] = value
	}
	resultMap["available_time"] = availableArray
	resultMap["id"] = resourceID
	resultMap["date"] = date

	return ctx.ResSuccess(resultMap)
}

// Create 创建预定资源
func (a *PublicResourceController) Create(ctx *context.Context) error {
	ctx.WriteOperateLog("PublicResourceController.Create", "移动端-公共资源-创建资源预定")
	//	1.获取创建参数
	params := new(schema.ResourceReservedCParams)
	if err := ctx.ParseJSON(params); err != nil {
		return ctx.ResErrBadRequest(err)
	}
	//	2.创建存储数据库的item
	item := new(schema.ResourceReserved)
	//	3.根据请求资源的record_id查询资源信息详情
	resItem, err := a.ResourceBll.Get(params.ResourceID)
	if err != nil {
		return ctx.ResErrInternalServer(err)
	}
	if resItem == nil {
		return ctx.ResErrInternalServer(errors.New("空指针错误，或者当前资源的record_id失效"))
	}
	//	初始化map
	item.HoursReserved = make(map[string][]int)
	//	预约时长
	l := 0
	//	4.校验资源预定时间:循环检测申请的预定时间是否可用(遍历不同日期当前的时间段，判断是否可预定)
	for t, hoursArray := range params.HoursReserved {

		//	查询指定资源、指定日期 的预定情况
		reservedItems, err := a.ResourceReservedBll.QueryItems(params.ResourceID, t)
		//	检查错误
		if err != nil {
			return ctx.ResErrInternalServer(err)
		}
		//	集合:用于检查选择的时间是否不可选
		tempMap := make(map[int]int)
		for _, j := range resItem.AvailableTime {
			//	标记可选
			tempMap[j] = 1
		}
		//	遍历预定记录表
		for _, reservedItem := range reservedItems {
			//	指定日期的预定情况
			reservedHours := reservedItem.HoursReserved[t]
			for _, hour := range reservedHours {
				if hour > 23 || hour < 0 {
					return ctx.ResErrInternalServer(errors.New("数据库存储的hours_reserved存在超范围数据"))
				}
				reservedID := resItem.RecordID
				h, ok := tempMap[hour]
				if ok && h == 1 {
					//	当前预约时间可选
					//	设置标记
					tempMap[hour] = 2
				} else if ok && h == 2 {
					return ctx.ResErrInternalServer(errors.New("数据库表错误:存在相同预约时间数据:资源预定数据表:record_id:" + reservedID))
				} else if !ok {
					return ctx.ResErrInternalServer(errors.New("数据库表错误:预约时间不可选:资源预定数据表:record_id:" + reservedID))
				}
			}
		}
		//	循环检查是否可选
		for _, hour := range hoursArray {
			if hour > 23 || hour < 0 {
				return ctx.ResErrBadRequest(errors.New("选定时间超出范围:hours_reserved"))
			}
			//	标记为0
			h, ok := tempMap[hour]
			if ok && h == 2 {
				return ctx.ResErrBadRequest(errors.New("hours_reserved指定的预约时间存在部分被占用"))
			} else if !ok {
				return ctx.ResErrBadRequest(errors.New("hours_reserved指定的预约时间存在部分不可选"))
			}
		}
		//	合规预约日期时间
		item.HoursReserved[t] = hoursArray
		l += len(hoursArray)
	}
	//	5.校验价格和总费用
	if resItem.Price != params.Price {
		return ctx.ResErrBadRequest(errors.New("价格和系统单价不符"))
	}

	if err != nil {
		return ctx.ResErrInternalServer(errors.New("价格格式转换错误"))
	}
	if params.Price*l != params.TotalCost {
		return ctx.ResErrBadRequest(errors.New("预约单价和时长 与总价不符"))
	}
	//	6.传递创建参数
	item.ResourceID = params.ResourceID
	item.ApplicantName = params.ApplicantName
	item.ApplicantTel = params.ApplicantTel
	item.ApplicantEnterprise = params.ApplicantEnterprise
	item.MemoUsed = params.MemoUsed
	item.Price = params.Price
	item.TotalCost = params.TotalCost

	item.ID = 0
	item.RecordID = util.UUID()
	item.Creator = ctx.GetUserID()
	item.Created = time.Now().Unix()
	item.Deleted = 0
	item.Status = 1
	item.ApplicationStatus = 0
	item.Comment = ""
	item.TimeHandled = 0
	item.Note = ""
	//	7.调用创建
	err = a.ResourceReservedBll.Create(item)
	if err != nil {
		return ctx.ResErrInternalServer(err)
	}

	return ctx.ResOK()
}

func (a *PublicResourceController) Update(ctx *context.Context) error {
	ctx.WriteOperateLog("PublicResourceController.Update", "移动端-公共资源-创建资源预定")
	//	更新参数
	params := new(schema.ResourceReservedUParams)
	if err := ctx.ParseJSON(params); err != nil {
		return ctx.ResErrBadRequest(err)
	}
	//
	reservedItem, err := a.ResourceReservedBll.Get(params.RecordID)
	if err != nil {
		return ctx.ResErrInternalServer(err)
	}
	if reservedItem == nil {
		return ctx.ResErrInternalServer(errors.New("空指针错误，或者预约的record_id失效" + params.RecordID))
	}
	if reservedItem.ApplicationStatus == 0 {

	}
	if reservedItem.Status == 1 && reservedItem.Comment == "" && reservedItem.TimeHandled == 0 {
		// TODO 取消申请(物业审核之后的申请才能被取消，且是有物业管理员进行取消)
		// 更新审批信息
		//	TODO 超时是否可审批
		info := make(map[string]interface{})
		info["time_handled"] = time.Now().Unix()
		info["comment"] = params.Comment
		info["application_status"] = params.UpdateType
		err := a.ResourceReservedBll.Update(params.RecordID, info)
		if err != nil {
			return ctx.ResErrInternalServer(err)
		}
	} else {
		return ctx.ResErrInternalServer(errors.New("当前预约信息错误:不能审批或取消申请(可能已被处理审批或者取消申请)"))
	}
	return ctx.ResOK()
}

// QueryReservedPage 申请人查询资源预定列表
func (a *PublicResourceController) QueryReservedPage(ctx *context.Context) error {
	ctx.WriteOperateLog("PublicResourceController.QueryReservedPage", "公共资源预定-申请人查询资源预定列表")
	//	TODO 验证当前用户的身份，是否为申请人类型
	userID := ctx.GetUserID()
	params := new(schema.ResourceReservedQParams)
	params.UserID = userID
	params.PageIndex = ctx.GetPageIndex()
	params.PageSize = ctx.GetPageSize()
	params.ApplicationStatus = ctx.QueryInt("application_status")
	if params.ApplicationStatus != 0 && params.ApplicationStatus != 1 {
		return ctx.ResErrBadRequest(errors.New("application_status参数错误"))
	}
	total, items, err := a.ResourceReservedBll.QueryReservedPage(params)
	if err != nil {
		return ctx.ResErrInternalServer(err)
	}
	list := make([]map[string]interface{}, 0)
	for _, item := range items {
		tempMap := make(map[string]interface{})
		tempMap["record_id"] = item.RecordID
		tempMap["resource_id"] = item.ResourceID
		tempMap["hours_reserved"] = item.HoursReserved
		tempMap["application_status"] = item.ApplicationStatus
		tempMap["created"] = item.Created

		//	查询资源基本信息详情
		resItem, err := a.ResourceBll.Get(item.ResourceID)
		if err != nil {
			return ctx.ResErrInternalServer(err)
		}
		if resItem == nil {
			return ctx.ResErrInternalServer(errors.New("空指针错误，或者当前资源的record_id失效" + item.ResourceID))
		}
		classItem, err := a.ResourceClassBll.Get(resItem.ClassificationID)
		if err != nil {
			return ctx.ResErrInternalServer(err)
		}
		if classItem == nil {
			return ctx.ResErrInternalServer(errors.New("空指针错误，或者当前资源分类的record_id失效" + resItem.ClassificationID))
		}
		tempMap["resource_type"] = classItem.ClassificationName
		//	资源所属区域名称
		if resItem.AddressZone == "" {
			return ctx.ResErrInternalServer(errors.New("资源所属区域的record_id为空"))
		}
		fullName, err := a.ParkBll.QueryFullName(resItem.AddressZone)
		if err != nil {
			return ctx.ResErrInternalServer(err)
		}
		tempMap["address_zone"] = fullName
		//	地址
		tempMap["address"] = resItem.Address
		//	可用状态
		tempMap["available_status"] = resItem.AvailableStatus
		//	资源图片
		tempMap["pictures"] = resItem.Pictures

		list = append(list, tempMap)
	}

	result := map[string]interface{}{
		"list": list,
		"pagination": map[string]interface{}{
			"total":    total,
			"current":  params.PageIndex,
			"pageSize": params.PageSize,
		},
	}

	return ctx.ResSuccess(result)
}

// QueryPage 物业人员查询申请列表
func (a *PublicResourceController) QueryPage(ctx *context.Context) error {
	ctx.WriteOperateLog("PublicResourceController.QueryPage", "公共资源预定-物业管理人员查询资源预定列表")
	//	TODO 验证当前用户的身份，是否为物业管理员类型
	userID := ctx.GetUserID()
	params := new(schema.ResourceReservedQParams)
	params.UserID = userID
	params.PageIndex = ctx.GetPageIndex()
	params.PageSize = ctx.GetPageSize()
	params.ApplicationStatus = ctx.QueryInt("application_status")
	if params.ApplicationStatus != 0 && params.ApplicationStatus != 1 {
		return ctx.ResErrBadRequest(errors.New("application_status参数错误"))
	}
	total, items, err := a.ResourceReservedBll.QueryReservedPage(params)
	if err != nil {
		return ctx.ResErrInternalServer(err)
	}
	list := make([]map[string]interface{}, 0)
	for _, item := range items {
		tempMap := make(map[string]interface{})
		tempMap["record_id"] = item.RecordID
		tempMap["resource_id"] = item.ResourceID
		tempMap["application_status"] = item.ApplicationStatus
		tempMap["comment"] = item.Comment
		tempMap["created"] = item.Created
		tempMap["time_handled"] = item.TimeHandled

		//	查询资源基本信息详情
		resItem, err := a.ResourceBll.Get(item.ResourceID)
		if err != nil {
			return ctx.ResErrInternalServer(err)
		}
		if resItem == nil {
			return ctx.ResErrInternalServer(errors.New("空指针错误，或者当前资源的record_id失效" + item.ResourceID))
		}
		classItem, err := a.ResourceClassBll.Get(resItem.ClassificationID)
		if err != nil {
			return ctx.ResErrInternalServer(err)
		}
		if classItem == nil {
			return ctx.ResErrInternalServer(errors.New("空指针错误，或者当前资源分类的record_id失效" + resItem.ClassificationID))
		}
		tempMap["resource_type"] = classItem.ClassificationName
		//	资源管理员
		tempMap["manager"] = resItem.Manager
		//	管理员电话
		tempMap["telephone"] = resItem.Telephone
		//	资源所属区域名称
		if resItem.AddressZone == "" {
			return ctx.ResErrInternalServer(errors.New("资源所属区域的record_id为空"))
		}
		fullName, err := a.ParkBll.QueryFullName(resItem.AddressZone)
		if err != nil {
			return ctx.ResErrInternalServer(err)
		}
		tempMap["address_zone"] = fullName
		//	地址
		tempMap["address"] = resItem.Address
		//	可用状态
		tempMap["available_status"] = resItem.AvailableStatus
		// 资源描述
		tempMap["describe"] = resItem.Comment
		//	资源图片
		tempMap["pictures"] = resItem.Pictures

		list = append(list, tempMap)
	}

	result := map[string]interface{}{
		"list": list,
		"pagination": map[string]interface{}{
			"total":    total,
			"current":  params.PageIndex,
			"pageSize": params.PageSize,
		},
	}

	return ctx.ResSuccess(result)
}

// QueryReserveDetail 查询预定详情
func (a *PublicResourceController) QueryReserveDetail(ctx *context.Context) error {
	ctx.WriteOperateLog("PublicResourceController.QueryReserveDetail", "移动端-公共资源-查询资源当前预定情况")
	//	资源的record_id
	reserveID := ctx.Query("reserve_id")
	if reserveID == "" {
		return ctx.ResErrBadRequest(errors.New("reserve_id参数错误"))
	}
	//	查询预定详情
	reserveItem, err := a.ResourceReservedBll.Get(reserveID)
	if err != nil {
		return ctx.ResErrInternalServer(err)
	}
	if reserveItem == nil {
		return ctx.ResErrInternalServer(errors.New("空指针错误，或者参数reserve_id失效"))
	}
	//	查询资源详情
	resItem, err := a.ResourceBll.Get(reserveItem.ResourceID)
	if err != nil {
		return ctx.ResErrInternalServer(err)
	}
	if resItem == nil {
		return ctx.ResErrInternalServer(errors.New("空指针错误，或者当前资源的record_id失效" + reserveItem.ResourceID))
	}
	resultMap := make(map[string]interface{})
	//	资源管理员
	resultMap["manager"] = resItem.Manager
	//	管理员电话
	resultMap["telephone"] = resItem.Telephone

	//	资源所属区域名称
	if resItem.AddressZone == "" {
		return ctx.ResErrInternalServer(errors.New("资源所属区域的record_id为空"))
	}
	fullName, err := a.ParkBll.QueryFullName(resItem.AddressZone)
	if err != nil {
		return ctx.ResErrInternalServer(err)
	}
	resultMap["address_zone"] = fullName

	//	地址
	resultMap["address"] = resItem.Address

	//	可用状态
	resultMap["available_status"] = resItem.AvailableStatus
	//	价格
	resultMap["price"] = resItem.Price

	// 资源描述
	resultMap["comment"] = resItem.Comment
	//	资源图片
	resultMap["pictures"] = resItem.Pictures

	resultMap["record_id"] = reserveItem.RecordID
	resultMap["resource_id"] = reserveItem.ResourceID
	resultMap["applicant_name"] = reserveItem.ApplicantName
	resultMap["applicant_tel"] = reserveItem.ApplicantTel
	resultMap["applicant_enterprise"] = reserveItem.ApplicantEnterprise
	resultMap["memo_used"] = reserveItem.MemoUsed
	resultMap["total_cost"] = reserveItem.TotalCost
	resultMap["application_status"] = reserveItem.ApplicationStatus
	resultMap["reserve_comment"] = reserveItem.Comment
	resultMap["created"] = reserveItem.Created
	resultMap["time_handled"] = reserveItem.TimeHandled
	resultMap["hours_reserved"] = reserveItem.HoursReserved

	return ctx.ResSuccess(resultMap)
}
